using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using ZeroSum.Domain.Entities;

namespace ZeroSum.Domain.Repositories;

public interface IRepository<TEntity, in TKey> : IRepository<TEntity> where TEntity : BaseEntity<TKey>
{
    void Remove(TKey id);

    Task RemoveAsync(TKey id);

    void RemoveRange(IEnumerable<TKey> ids);

    Task RemoveRangeAsync(IEnumerable<TKey> ids);

    TEntity Get(TKey id);

    Task<TEntity> GetAsync(TKey id);
}

public interface IRepository<TEntity> where TEntity : class, IEntity
{
    #region 添加

    /// <summary>
    ///     新增实体
    /// </summary>
    /// <param name="entity"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    TEntity Add([NotNull] TEntity entity);

    /// <summary>
    ///     异步新增实体
    /// </summary>
    /// <param name="entity"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task<TEntity> AddAsync([NotNull] TEntity entity);

    /// <summary>
    ///     批量新增实体
    /// </summary>
    /// <param name="entities"></param>
    /// <typeparam name="TEntity"></typeparam>
    void AddRange(IEnumerable<TEntity> entities);

    /// <summary>
    ///     异步批量新增实体
    /// </summary>
    /// <param name="entities"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task AddRangeAsync(IEnumerable<TEntity> entities);

    #endregion

    #region 更新

    /// <summary>
    ///     更新实体
    /// </summary>
    /// <param name="entity"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    TEntity Update([NotNull] TEntity entity);

    /// <summary>
    ///     异步更新实体
    /// </summary>
    /// <param name="entity"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task<TEntity> UpdateAsync([NotNull] TEntity entity);

    /// <summary>
    ///     批量更新实体
    /// </summary>
    /// <param name="entities"></param>
    /// <typeparam name="TEntity"></typeparam>
    void UpdateRange(IEnumerable<TEntity> entities);

    /// <summary>
    ///     异步批量更新实体
    /// </summary>
    /// <param name="entities"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task UpdateRangeAsync(IEnumerable<TEntity> entities);

    #endregion

    #region 查询

    /// <summary>
    ///     Query查询
    /// </summary>
    /// <returns></returns>
    IQueryable<TEntity> Query();

    /// <summary>
    ///     查询单条数据
    /// </summary>
    /// <param name="query"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    TEntity Get(IQuery<TEntity> query);

    /// <summary>
    ///     异步查询单条数据
    /// </summary>
    /// <param name="query"></param>
    /// <returns></returns>
    Task<TEntity> GetAsync(IQuery<TEntity> query);

    /// <summary>
    ///     查询多条数据
    /// </summary>
    /// <param name="query"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    IList<TEntity> GetList(IQuery<TEntity> query);

    /// <summary>
    ///     异步查询多条数据
    /// </summary>
    /// <param name="query"></param>
    /// <returns></returns>
    Task<IList<TEntity>> GetListAsync(IQuery<TEntity> query);

    /// <summary>
    ///     查询单个实体
    /// </summary>
    /// <param name="predicate">查询表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    TEntity Get([NotNull] Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    ///     异步查询单个实体
    /// </summary>
    /// <param name="predicate">查询表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task<TEntity> GetAsync([NotNull] Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    ///     条件查询
    /// </summary>
    /// <param name="predicate">查询表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    IList<TEntity> GetList([NotNull] Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    ///     异步条件查询
    /// </summary>
    /// <param name="predicate">查询表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task<IList<TEntity>> GetListAsync([NotNull] Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    ///     分页查询
    /// </summary>
    /// <param name="pageNumber">要查询的第几页</param>
    /// <param name="pageSize">每页数量</param>
    /// <param name="sorting">排序</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    IList<TEntity> GetPage(int pageNumber, int pageSize, Expression<Func<TEntity, object>> sorting);

    /// <summary>
    ///     异步分页查询
    /// </summary>
    /// <param name="pageNumber">要查询的第几页</param>
    /// <param name="pageSize">每页数量</param>
    /// <param name="sorting">排序</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task<IList<TEntity>> GetPageAsync(int pageNumber, int pageSize, Expression<Func<TEntity, object>> sorting);

    #endregion

    #region 删除

    /// <summary>
    ///     删除实体
    /// </summary>
    /// <param name="entity"></param>
    /// <typeparam name="TEntity"></typeparam>
    void Remove([NotNull] TEntity entity);

    /// <summary>
    ///     异步删除实体
    /// </summary>
    /// <param name="entity"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task RemoveAsync([NotNull] TEntity entity);

    /// <summary>
    ///     条件删除实体
    /// </summary>
    /// <param name="predicate">条件表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    void Remove([NotNull] Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    ///     异步条件删除实体
    /// </summary>
    /// <param name="predicate">条件表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task RemoveAsync([NotNull] Expression<Func<TEntity, bool>> predicate);


    /// <summary>
    ///     批量删除
    /// </summary>
    /// <param name="entities"></param>
    /// <typeparam name="TEntity"></typeparam>
    void RemoveRange(IEnumerable<TEntity> entities);

    /// <summary>
    ///     异步批量删除
    /// </summary>
    /// <param name="entities"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task RemoveRangeAsync(IEnumerable<TEntity> entities);

    /// <summary>
    ///     批量条件删除
    /// </summary>
    /// <param name="predicate">条件表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    void RemoveRange(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    ///     异步批量条件删除
    /// </summary>
    /// <param name="predicate">条件表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task RemoveRangeAsync(Expression<Func<TEntity, bool>> predicate);


    /// <summary>
    ///     通过Query匹配删除单条记录
    /// </summary>
    /// <param name="query"></param>
    /// <typeparam name="TEntity"></typeparam>
    void Remove(IQuery<TEntity> query);


    /// <summary>
    ///     异步通过Query匹配删除单条记录
    /// </summary>
    /// <param name="query"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task RemoveAsync(IQuery<TEntity> query);

    /// <summary>
    ///     通过Query匹配删除多条记录
    /// </summary>
    /// <param name="query"></param>
    /// <typeparam name="TEntity"></typeparam>
    void RemoveRange(IQuery<TEntity> query);

    /// <summary>
    ///     通过Query匹配删除多条记录
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    void RemoveRange();

    /// <summary>
    ///     异步通过Query匹配删除多条记录
    /// </summary>
    /// <param name="query"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task RemoveRangeAsync(IQuery<TEntity> query);

    #endregion

    #region 辅助方法

    /// <summary>
    ///     统计总数
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    int Count();

    /// <summary>
    ///     异步统计总数
    /// </summary>
    /// <returns></returns>
    Task<int> CountAsync();

    /// <summary>
    ///     查询是否存在符合条件的实体
    /// </summary>
    /// <param name="predicate">查询表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    bool Any(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    ///     异步查询是否存在符合条件的实体
    /// </summary>
    /// <param name="predicate">查询表达式</param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    ///     查询是否实体是否存在
    /// </summary>
    /// <param name="query"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    bool Existed(IQuery<TEntity> query);

    /// <summary>
    ///     异步查询实体是否存在
    /// </summary>
    /// <param name="query"></param>
    /// <returns></returns>
    Task<bool> ExistedAsync(IQuery<TEntity> query);

    /// <summary>
    ///     统计总数
    /// </summary>
    /// <param name="query"></param>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    int Count(IQuery<TEntity> query);

    /// <summary>
    ///     异步统计总数
    /// </summary>
    /// <param name="query"></param>
    /// <returns></returns>
    Task<int> CountAsync(IQuery<TEntity> query);

    #endregion

    #region 工作单元操作

    /// <summary>
    ///     保存修改
    /// </summary>
    void SaveChanges();

    /// <summary>
    ///     异步保存修改
    /// </summary>
    /// <returns></returns>
    Task SaveChangesAsync();

    #endregion
}